package pa165.dominatingspecies.service.impl;

import java.util.ArrayList;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import pa165.dominating.species.dao.EnvironmentDao;
import pa165.dominating.species.entities.Environment;
import pa165.dominating.species.exceptions.DataStorageException;
import pa165.dominating.species.exceptions.ToException;
import pa165.dominating.species.service.EnvironmentService;
import pa165.dominatingspecies.service.converter.EnvironmentConverter;
import pa165.dominating.species.tos.EnvironmentTo;

/**
 * @author Stanislau Dubrouski
 */
@Service
public class EnvironmentServiceImpl implements EnvironmentService {

    @Autowired
    private EnvironmentDao envDao;
    @Autowired
    private EnvironmentConverter envConverter;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @PreAuthorize("hasRole('ADMIN')")
    public void createEnvironment(EnvironmentTo env) {
        if (env == null) {
            throw new ToException("EnvironmentTo cannot be null");
        }
        if (env.getId() != null) {
            throw new ToException("EnvironmentTo cannot have assigned id while creating.");
        }
        Environment environment = envConverter.convertEnvironmentTo2Environment(env);
        try {
            envDao.createEnvironment(environment);
        } catch (Exception ex) {
            throw new DataStorageException("Could not store environment"
                    + environment.toString(), ex);
        }
        if (environment.getId() == null) {
            throw new IllegalStateException("Id was not assigned after new Environment was created");
        }

        env.setId(environment.getId());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @PreAuthorize("hasRole('ADMIN')")
    public void deleteEnvironment(EnvironmentTo env) {
        if (env == null) {
            throw new ToException("EnvironmentTo cannot be null");
        }
        if (env.getId() == null) {
            throw new ToException("EnvironmentTo id cannot be null");
        }
        Environment environment = envConverter.convertEnvironmentTo2Environment(env);
        try {
            envDao.deleteEnvironment(environment);
        } catch (Exception ex) {
            throw new DataStorageException("Could not delete environment"
                    + environment.toString(), ex);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @PreAuthorize("hasRole('WORKER')")
    public EnvironmentTo getEnvironmentById(Long id) {
        if (id == null) {
            throw new ToException("Id for searching cannot be null");
        }
        try {
            return envConverter.convertEnvironment2EnvironmentTo(envDao.getEnvironmentById(id));
        } catch (Exception ex) {
            throw new DataStorageException("Could not get environment with id "
                    + id.toString(), ex);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @PreAuthorize("hasRole('WORKER')")
    public EnvironmentTo updateEnvironment(EnvironmentTo env) {
        if (env == null) {
            throw new ToException("EnvironmentTo cannot be null");
        }

        if (env.getId() == null) {
            throw new ToException("EnvironmentTo must have assigned id while updating.");
        }
        Environment environment = envConverter.convertEnvironmentTo2Environment(env);
        try {
            envDao.updateEnvironment(environment);
        } catch (Exception ex) {
            throw new DataStorageException("Could not update environment "
                    + environment.toString(), ex);
        }
        return envConverter.convertEnvironment2EnvironmentTo(environment);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @PreAuthorize("hasRole('WORKER')")
    public List<EnvironmentTo> getAllEnvironments() {
        List<Environment> found;
        List<EnvironmentTo> tos = new ArrayList<>();
        try {
            found = envDao.getAllEnvironments();
        } catch (Exception ex) {
            throw new DataStorageException("Error while getting all environments", ex);
        }

        for (Environment e : found) {
            tos.add(envConverter.convertEnvironment2EnvironmentTo(e));
        }

        return tos;
    }

    public void setEnvDao(EnvironmentDao envDao) {
        this.envDao = envDao;
    }

    public void setEnvConverter(EnvironmentConverter envConverter) {
        this.envConverter = envConverter;
    }
}
